package com.net.xpay.admin.controller.admin;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.net.common.exception.BusinessException;
import com.net.common.model.ResultData;
import com.net.common.model.ResultPagedList;
import com.net.common.util.LocalDateUtil;
import com.net.common.util.SerializationUtil;
import com.net.xpay.admin.vo.UserSafePayMonthBillVo;
import com.net.xpay.admin.vo.UserSafePayTransMonthStatExportVo;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.domain.stat.UserSafePayTransMonthStat;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.common.manager.stat.UserSafePayTransMonthStatManager;
import com.net.xpay.core.constant.PoseidonErrorCode;
import com.net.xpay.core.manager.ChargeRecordManager;
import com.net.xpay.core.model.UserSafePayTransMonthStatBillModel;
import com.net.xpay.core.model.UserSafePayTransMonthStatSearchModel;
import com.net.xpay.core.utils.BeanCopierUtil;
import com.net.xpay.core.utils.JxlsUtils;
import com.net.shard.ShardDataSource;
import com.net.shard.ShardDataSourceConfigurer;
import com.net.shard.ShardUtil;
import com.net.shard.domain.ShardConfig;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户安全付月转账统计
 **/
@Slf4j
@RestController
@RequestMapping("/admin/user-safe-pay-trans-month-stat")
@Api(tags = "运营/用户安全付月转账统计",description = "用户安全付月转账统计")
public class AdminUserSafePayTransMonthStatController {

    @Autowired
    private UserSafePayTransMonthStatManager userSafePayTransMonthStatManager;

    @Autowired
    private ChargeRecordManager chargeRecordManager;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    @Qualifier("shardDataSource")
    private DataSource shardDataSource;


    @ApiOperation(value = "用户安全付月转账统计")
    @PostMapping(value = "/search")
    @PreAuthorize("hasAnyRole('ADMIN', 'user-safe-pay-trans-month-stat::search')")
    public ResultPagedList<UserSafePayTransMonthStat> search(@RequestBody UserSafePayTransMonthStatSearchModel searchModel){
        // 根据查询条件进行查询
        List<UserSafePayTransMonthStat> userTransMonthStatList = userSafePayTransMonthStatManager.search(searchModel);
        // 查询带条件后数据的条数
        long count = userSafePayTransMonthStatManager.searchCount(searchModel);
        return new ResultPagedList<>(userTransMonthStatList,count,searchModel);
    }

    /**
     * 月账单导出
     */
    @ApiOperation("月账单明细导出")
    @GetMapping("/export-month-bill")
    public ResultData<Boolean> export(@ApiIgnore HttpServletRequest request, @ApiIgnore HttpServletResponse response, String searchModelJson) {
        Preconditions.checkArgument(searchModelJson != null);
        UserSafePayTransMonthStatSearchModel model = SerializationUtil.str2Object(searchModelJson, UserSafePayTransMonthStatSearchModel.class);

        UserSafePayTransMonthStatSearchModel searchModel = new UserSafePayTransMonthStatSearchModel();
        searchModel.setMinNotFreeSuccessCount(1L);
        searchModel.setYear(model.getYear());
        searchModel.setMonth(model.getMonth());
        List<UserSafePayTransMonthStat> userSafePayTransMonthStats = userSafePayTransMonthStatManager.list(searchModel);

        List<UserSafePayTransMonthStatExportVo> vos = BeanCopierUtil.batchCopy(UserSafePayTransMonthStat.class, UserSafePayTransMonthStatExportVo.class, userSafePayTransMonthStats);
        for (UserSafePayTransMonthStatExportVo vo : vos) {
            String month = vo.getMonth() + "";
            if (vo.getMonth() < 10) {
                month = "0" + month;
            }
            vo.setMonthYear(vo.getYear() + "-" + month);
            vo.setServiceFee(new BigDecimal(vo.getFinalServicePrice()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP).toString());
            LocalDateTime day = LocalDateTime.of(vo.getYear(), vo.getMonth(), 1, 0, 0);
            LocalDateTime startTime = LocalDateUtil.getMonthStartDay(day);
            LocalDateTime endTime = LocalDateUtil.getMonthEndDay(day);

            try {
                UserShard userShard = userShardManager.getById(vo.getUserId());
                ShardUtil.setShardContext(userShard.getShardId());
                long chargeAmount = chargeRecordManager.statUserAmountByAlipayAppQrcode(vo.getUserId(), startTime, endTime);
                vo.setChargeAmount(new BigDecimal(chargeAmount).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP).toString());
            } finally {
                ShardUtil.cleanShardContext();
            }
        }
        // 定义一个Map，往里面放入要在模板中显示数据
        Map<String, Object> params = new HashMap<>();

        params.put("records", vos);

        String month = searchModel.getMonth() + "";
        if (searchModel.getMonth() < 10) {
            month = "0" + month;
        }
        String fileName = searchModel.getYear() + "-" + month  + "结算明细.xlsx";
        String template = "/excel/tpl/结算明细.xls";

        InputStream is;
        try {
            //获取模板流
            is = getClass().getResourceAsStream(template);

            //火狐游览器中文文件名会有乱码,兼容火狐
            String agent = request.getHeader("USER-AGENT").toLowerCase();

            if (!Strings.isNullOrEmpty(agent) && (agent.contains("firefox") || agent.contains("safari"))) {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            }
            response.setContentType("application/force-download");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            JxlsUtils.exportExcel(is, response.getOutputStream(), params);
            response.flushBuffer();
        } catch (IOException e) {
            log.warn("export error", e);
        }
        return new ResultData<>();
    }

    @ApiOperation(value = "用户安全付月账单统计")
    @PostMapping(value = "/stat-month-bill")
    @PreAuthorize("hasAnyRole('ADMIN')")
    public ResultData<UserSafePayMonthBillVo> statMonthBill(@RequestBody UserSafePayTransMonthStatBillModel billModel) {
        if (billModel.getYear() == null || billModel.getMonth() == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "请选择月份");
        }
        UserSafePayTransMonthStatSearchModel searchModel = new UserSafePayTransMonthStatSearchModel();
        searchModel.setMinNotFreeSuccessCount(1L);
        searchModel.setYear(billModel.getYear());
        searchModel.setMonth(billModel.getMonth());
        List<UserSafePayTransMonthStat> userSafePayTransMonthStats = userSafePayTransMonthStatManager.list(searchModel);

        BigDecimal alipayAmount = new BigDecimal("0.00");
        BigDecimal bankAmount = new BigDecimal("0.00");
        BigDecimal finalServicePrice = new BigDecimal("0.00");
        for (UserSafePayTransMonthStat stat : userSafePayTransMonthStats) {
            alipayAmount = alipayAmount.add(new BigDecimal(stat.getNotFreeSuccessAlipayAmount()));
            bankAmount = bankAmount.add(new BigDecimal(stat.getNotFreeSuccessBankAmount()));
            finalServicePrice = finalServicePrice.add(new BigDecimal(stat.getFinalServicePrice()));
        }

        UserSafePayMonthBillVo vo = new UserSafePayMonthBillVo();

        vo.setYear(billModel.getYear());
        vo.setMonth(billModel.getMonth());
        vo.setSuccessAlipayAmount(alipayAmount.toString());
        vo.setSuccessBankAmount(bankAmount.toString());
        vo.setFinalServiceFee(finalServicePrice.multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP).toString());

        BigDecimal bankTransCost = bankAmount.multiply(new BigDecimal("0.001")).setScale(2, RoundingMode.HALF_UP);
        vo.setBankTransCost(bankTransCost.toString());

        //月充值数据 只算收取手续费的
        // 根据当前时间获取改天的起始时间和结束时间
        long totalChargeAmount = 0L;
        ShardDataSourceConfigurer shardDataSourceConfigurer = ((ShardDataSource) shardDataSource).getShardDataSourceConfigurer();
        Map<Long, ShardConfig> shardConfigMap = shardDataSourceConfigurer.getShardConfigMap();
        for (Long shardId : shardConfigMap.keySet()) {
            try {
                ShardUtil.setShardContext(shardId);
                LocalDateTime day = LocalDateTime.of(billModel.getYear(), billModel.getMonth(), 1, 0, 0);
                LocalDateTime startTime = LocalDateUtil.getMonthStartDay(day);
                LocalDateTime endTime = LocalDateUtil.getMonthEndDay(day);

                long chargeAmount = chargeRecordManager.statAmountByAlipayAppQrcode(startTime, endTime);
                totalChargeAmount += chargeAmount;
            } finally {
                ShardUtil.cleanShardContext();
            }
        }


        vo.setChargeAmount(new BigDecimal(totalChargeAmount).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP).toString());
        vo.setChargeCost(new BigDecimal(vo.getChargeAmount()).multiply(new BigDecimal("0.006")).setScale(2, RoundingMode.HALF_UP).toString());

        BigDecimal totalBenefitFee = new BigDecimal(vo.getFinalServiceFee()).subtract(new BigDecimal(vo.getBankTransCost()))
                .subtract(new BigDecimal(vo.getChargeCost())).multiply(new BigDecimal("0.2")).setScale(2, RoundingMode.HALF_UP);
        vo.setTotalBenefitFee(totalBenefitFee.toString());

        //老数据 支付宝转账金额 * 0.006 * 0.994 * 0.2
        //到卡转账金额 * 0.005 * 0.994 * 0.2
        BigDecimal alipayBenefitFee = alipayAmount.multiply(new BigDecimal("0.006")).multiply(new BigDecimal("0.994")).multiply(new BigDecimal("0.2")).setScale(2, RoundingMode.HALF_UP);
        BigDecimal bankBenefitFee = bankAmount.multiply(new BigDecimal("0.005")).multiply(new BigDecimal("0.994")).multiply(new BigDecimal("0.2")).setScale(2, RoundingMode.HALF_UP);

        vo.setAlipayBenefitFee(alipayBenefitFee.toString());
        vo.setBankBenefitFee(bankBenefitFee.toString());
        vo.setOldTotalBenefitFee(alipayBenefitFee.add(bankBenefitFee).toString());


        return new ResultData<>(vo);
    }

    /**
     * 安全付转账月统计记录导出
     */
    @ApiOperation("安全付转账月统计记录导出")
    @GetMapping("/export")
    public ResultData<Boolean> exportSafePayTransMonthStat(@ApiIgnore HttpServletRequest request, @ApiIgnore HttpServletResponse response, String searchModelJson) {
        Preconditions.checkArgument(searchModelJson != null);

        UserSafePayTransMonthStatSearchModel searchModel = SerializationUtil.str2Object(searchModelJson, UserSafePayTransMonthStatSearchModel.class);
        long count = userSafePayTransMonthStatManager.searchCount(searchModel);
        if (count >= 10000L){
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "记录超过10000条，无法导出");
        }
        List<UserSafePayTransMonthStat> userSafePayTransMonthStatList = userSafePayTransMonthStatManager.list(searchModel);

        // 定义一个Map，往里面放入要在模板中显示数据
        Map<String, Object> model = new HashMap<>();

        model.put("records", userSafePayTransMonthStatList);

        String fileName = "安全付转账月统计记录.xlsx";
        String template = "/excel/tpl/安全付转账月统计记录.xls";

        InputStream is;
        try {
            //获取模板流
            is = getClass().getResourceAsStream(template);

            //火狐游览器中文文件名会有乱码,兼容火狐
            String agent = request.getHeader("USER-AGENT").toLowerCase();

            if (!Strings.isNullOrEmpty(agent) && (agent.contains("firefox") || agent.contains("safari"))) {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            }
            response.setContentType("application/force-download");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            JxlsUtils.exportExcel(is, response.getOutputStream(), model);
            response.flushBuffer();
        } catch (IOException e) {
            log.warn("export error", e);
        }
        return new ResultData<>();
    }

}